package cc.linker.steplink.crm.service.impl;

import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.dao.*;
import cc.linker.steplink.crm.domain.*;
import cc.linker.steplink.crm.response.GlobalException;
import cc.linker.steplink.crm.response.ResponseException;
import cc.linker.steplink.crm.service.ICustomerBindService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class CustomerBindServiceImpl implements ICustomerBindService {
    @Autowired
    private PersonalDao personalDao;
    @Autowired
    private HttpService httpService;
    @Autowired
    private SyncContentDao syncContentDao;
    @Autowired
    private CustomerBindDao customerBindDao;
    @Autowired
    private SyncDao syncDao;
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private SystemProperties systemProperties;

    @Override
    public void joinArticleShare(BindUserDto bindUser,String customerId) throws GlobalException {
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByGlobalOpenid(globalOpenid);
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByOpenidAndToken(bindUser.getOpenid(),bindUser.getToken());
        CustomerBindRelation bindRelation = customerBindDao.findBindRelationByCustomerId(customerId);
        if (bindRelation != null) {
            Integer staffType = bindRelation.getStaffType();
            if (CustomerBindRelation.StaffType.INNER_STAFF.getType().equals(staffType)) {
                customerBindDao.updateBindRelationAndCreateTime(bindRelation.getCustomerId(),
                        CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType());
            } else {
                throw new GlobalException(new ResponseException(400, "已加文章分享"));
            }
        } else {
            //Customer customer = syncContentDao.findCustomerByGlobalOpenid(globalOpenid);
            //Customer customer = syncContentDao.findCustomerByOpenidAndToken(bindUser.getOpenid(), bindUser.getToken());
            Customer customer = syncContentDao.findCustomerByCustomerId(customerId);
            if (customer != null) {
                // 加入文章分享
                insertCustomerBindRelation(customer, bindUser,
                        CustomerBindRelation.StaffType.OUTTER_STAFF.getType(),null);
            } else {
                throw new GlobalException(new ResponseException(400, "无用户"));
            }
        }
    }

    /**
     * 保存绑定关系
     * @param customer
     * @param openid
     * @param
     */
    private void insertCustomerBindRelation(Customer customer, BindUserDto bindUser, Integer type, User user) {
        CustomerBindRelation relation = new CustomerBindRelation();
        relation.setCustomerId(customer.getCustomerId());
        relation.setGlobalOpenid(bindUser.getGlobalOpenid());
        relation.setOpenid(bindUser.getOpenid());
        relation.setToken(bindUser.getToken());
        relation.setStaffType(type);
        relation.setOrgId(customer.getOrgId());
        if (user != null) {
            relation.setUserCode(user.getAdminCode());
            relation.setUserId(user.getAdminId());
            if (StringUtils.isEmpty(customer.getOrgId())) {
                Integer updateCustomerByCustomerId = syncDao.updateCustomerByCustomerId(
                        customer.getCustomerId(), user.getOrgId());
                if (updateCustomerByCustomerId > 0) {
                    relation.setOrgId(user.getOrgId());
                }
            }
        }
        
        customerBindDao.insertCustomerBindRelation(relation);
    }

    @Override
    public void bindCustomerToStaff(BindUserDto bindUser,String customerId) throws GlobalException {
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByGlobalOpenid(bindUser.getGlobalOpenid());
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByOpenidAndToken(bindUser.getOpenid(),bindUser.getToken());
        CustomerBindRelation bindRelation = customerBindDao.findBindRelationByCustomerId(customerId);
        if (bindRelation != null) {
            Integer staffType = bindRelation.getStaffType();
            if (CustomerBindRelation.StaffType.INNER_STAFF.getType().equals(staffType)
                    || CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType().equals(staffType)) {
                throw new GlobalException(new ResponseException(400, "已绑定机构用户"));
            }
        }
        //Customer customer = syncContentDao.findCustomerByGlobalOpenid(bindUser.getGlobalOpenid());
        //Customer customer = syncContentDao.findCustomerByOpenidAndToken(bindUser.getOpenid(), bindUser.getToken());
        Customer customer = syncContentDao.findCustomerByCustomerId(customerId);
        if (customer != null) {
            String responseJson = null;
            try {
                responseJson = connectManageCenter(bindUser, ConnectType.BIND);
            } catch (URISyntaxException | IOException e) {
                e.printStackTrace();
                LOGGER.error("用户openid: [{}] , token: [{}] 绑定机构账户失败", customerId);
                throw new GlobalException(new ResponseException(400, "绑定机构账户失败"));
            }

            ResponseMsg responseMsg = JSON.parseObject(responseJson, ResponseMsg.class);
            if (responseMsg != null && 0 == responseMsg.getRetcode()) {
                // 绑定关系
                User user = userDao.getSimpleUser(bindUser.getUsercode());
                if (bindRelation != null) {
                    Integer staffType = bindRelation.getStaffType();
                    bindRelation.setCustomerId(customer.getCustomerId());
                    bindRelation.setOrgId(user.getOrgId());
                    bindRelation.setUserCode(user.getAdminCode());
                    bindRelation.setUserId(user.getAdminId());
                    bindRelation.setStaffType(CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType());
                    if (CustomerBindRelation.StaffType.OUTTER_STAFF.getType().equals(staffType)) {
                        customerBindDao.updateBindRelation(bindRelation);
                    } else {
                        throw new GlobalException(new ResponseException(400, "已绑定机构用户"));
                    }
                } else {
                    if (user != null) {
                        insertCustomerBindRelation(customer, bindUser,
                                CustomerBindRelation.StaffType.INNER_STAFF.getType(),user);
                    } else {
                        throw new GlobalException(new ResponseException(400, "机构用户不存在"));
                    }
                }
            } else {
                LOGGER.error("用户openid: [{}] , token: [{}] 绑定机构账户失败[{}]", bindUser.getOpenid(),bindUser.getToken(), responseJson);
                throw new GlobalException(new ResponseException(400, responseMsg != null?responseMsg.getErrmsg():"绑定机构账户失败"));
            }
        } else {
            throw new GlobalException(new ResponseException(400, "无用户"));
        }
    }

    /**
     * 
     * @param bindUser
     * @param connectType 绑定/取消绑定
     * @return
     */
    private String connectManageCenter(BindUserDto bindUser, ConnectType connectType) throws IOException, URISyntaxException {
        Map<String,Object> params = new HashMap<>();
        params.put("token",bindUser.getToken());
        Map<String,String> headers = new HashMap<>();
        headers.put("Content-Type","application/x-www-form-urlencoded");

        String responseJson = null;
        String manageCenterUrl = systemProperties.getManageCenter();
        if (!manageCenterUrl.endsWith("/")) {
            manageCenterUrl = manageCenterUrl + "/";
        }
        manageCenterUrl = manageCenterUrl + "ajax/admin.steplink/getInfo.aspx";
        switch (connectType) {
            case BIND :
                params.put("usercode",bindUser.getUsercode());
                params.put("openid",bindUser.getOpenid());
                params.put("userpwd", bindUser.getPwd());
                responseJson = httpService.doPost(manageCenterUrl + "?type=BindUser", params, headers);
                break;
            case UNBIND :
                params.put("usercode",bindUser.getUsercode());
                params.put("openid",bindUser.getOpenid());
                responseJson = httpService.doGet(manageCenterUrl + "?type=CancelBind", params, headers);
                break;
            case ORG_INFO :
                responseJson = httpService.doGet(manageCenterUrl + "?type=GetPublicInfo", params, headers);
                break;
            default:
                return null;
        }
        return responseJson;
        
    }

    @Override
    public void unbindCustomer(BindUserDto bindUser,String customerId) throws GlobalException {
        // 获取绑定关系
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByGlobalOpenid(bindUser.getGlobalOpenid());
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByOpenidAndToken(bindUser.getOpenid(),bindUser.getToken());
        CustomerBindRelation bindRelation = customerBindDao.findBindRelationByCustomerId(customerId);

        if (bindRelation != null) {
            Integer staffType = bindRelation.getStaffType();
            customerId = bindRelation.getCustomerId();
            if (CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType().equals(staffType)
                    || CustomerBindRelation.StaffType.INNER_STAFF.getType().equals(staffType)) {

                String responseJson = null;
                try {
                    bindUser.setUsercode(bindRelation.getUserCode());
                    responseJson = connectManageCenter(bindUser, ConnectType.UNBIND);
                } catch (URISyntaxException | IOException e) {
                    e.printStackTrace();
                    LOGGER.error("用户openid: [{}] , token: [{}] 取消绑定机构账户失败",customerId);
                    throw new GlobalException(new ResponseException(400, "取消绑定机构账户失败"));
                }

                ResponseMsg responseMsg = JSON.parseObject(responseJson, ResponseMsg.class);
                if (responseMsg != null && 0 == responseMsg.getRetcode()) {
                    // 取消绑定关系
                    User user = userDao.getSimpleUser(bindRelation.getUserCode());
                    if (CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType().equals(staffType)) {
                        bindRelation.setCustomerId(customerId);
                        bindRelation.setOrgId(user.getOrgId());
                        bindRelation.setUserCode(bindRelation.getUserCode());
                        bindRelation.setUserId(user.getAdminId());
                        bindRelation.setStaffType(CustomerBindRelation.StaffType.OUTTER_STAFF.getType());
                        customerBindDao.updateBindRelation(bindRelation);
                    } else {
                        customerBindDao.deleteBindRelation(customerId);
                    }
                } else {
                    LOGGER.error("用户openid: [{}] , token: [{}] 取消绑定机构账户失败[{}]", customerId , responseJson);
                    throw new GlobalException(new ResponseException(400, "取消绑定机构账户失败"));
                }
            } else {
                throw new GlobalException(new ResponseException(400, "未绑定机构账户"));
            }
        } else {
            throw new GlobalException(new ResponseException(400, "未绑定机构账户"));
        }
    }

    @Override
    public boolean checkCustomerBind(BindUserDto bindUser,String customerId) throws GlobalException {
        return checkBind(customerId, bindUser.getType());
    }

    @Override
    public WxOrgInfo getOrgInfo(BindUserDto bindUser) throws IOException, URISyntaxException {
        String responseJson = connectManageCenter(bindUser, ConnectType.ORG_INFO);
        ResponseMsg responseMsg = JSON.parseObject(responseJson, ResponseMsg.class);
        if (responseMsg != null && 0 == responseMsg.getRetcode()) {
            try {
                JSONObject data = JSON.parseObject(responseJson);
                JSONArray wx = data.getJSONArray("retobject");
                if (wx != null && wx.size() > 0) {
                    return wx.getObject(0, WxOrgInfo.class);
                } else{
                    LOGGER.info("请求管理中心公号信息成功，但无数据");
                }
            } catch (Exception e){
                LOGGER.info("解析失败");
            }
        }
        LOGGER.info("请求管理中心公号信息接口异常");
        return null;
    }

    @Override
    public WxOrgInfo getOrgInfo(BindUserDto bindUser, boolean justOrgcode) throws IOException, URISyntaxException {
        if (justOrgcode) {
            String orgId = customerBindDao.getOrgIdFromWeixinList(bindUser.getToken());
            if (!StringUtils.isEmpty(orgId)) {
                return new WxOrgInfo(orgId,null,null,null,null);
            }
        } else {
            return getOrgInfo(bindUser);
        }
        return null;
    }

    @Override
    public String getUsercode(BindUserDto bindUser) {
        // 获取绑定关系
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByGlobalOpenid(bindUser.getGlobalOpenid());
        CustomerBindRelation bindRelation = customerBindDao.findBindRelationByOpenidAndToken(bindUser.getOpenid(),bindUser.getToken());

        if (bindRelation != null) {
            return bindRelation.getUserCode();
        }
        return null;
    }

    @Override
    public Map getOpenIdAndToken(String customerId) {
        return customerBindDao.getOpenIdAndToken(customerId);
    }

    /**
     * 检查是否绑定
     * @param
     * @param
     */
    private boolean checkBind(String customerId, Integer serachType) {
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByGlobalOpenid(globalOpenid);
        //CustomerBindRelation bindRelation = customerBindDao.findBindRelationByOpenidAndToken(openid,token);
        CustomerBindRelation bindRelation = customerBindDao.findBindRelationByCustomerId(customerId);

        if (bindRelation == null) {
            // 未绑定
            return false;
        } else {
            Integer staffType = bindRelation.getStaffType();
            if (serachType.equals(staffType)) {
                return true;
            } else {
                if (CustomerBindRelation.StaffType.VALID_INNER_STAFF.getType().equals(staffType)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }

    @Getter
    @Setter
    static class ResponseMsg {
        private String errmsg;
        
        /**
         * 0成功 1用户验证失败 2其它失败信息
         */
        private int retcode;
    }

    @Getter
    @AllArgsConstructor
    enum ConnectType {
        BIND("bind"),UNBIND("unbind"),ORG_INFO("orgInfo");
        private String type;
    }
}
